﻿/// <reference path="jquery-1.4.2.js" />
var Eci = Eci || {}
Eci.IO = Eci.IO || {}

/**
 * 上传文件
 *
 */
Eci.IO.File = function (file) {
  /**
   * 文件尺寸(byte)
   */
  this.FileSize = file.size

  /**
   * 文件尺寸(byte)
   */
  this.SourceBaseFileSize = file.size

  /**
   * 文件
   */
  this.File = file

  /**
   * 文件类型
   */
  this.FileType = file.type

  /**
   * 文件名称
   */
  this.FileName = file.name

  /**
   * 文件在服务器上的路径
   */
  this.RealPath = ''

  /**
   * 文件分片尺寸
   */
  this.PageSize = 512 * 1024

  /**
   * 文件分片索引
   */
  this.PageIndex = 0

  /**
   * 文件分片总数
   */
  this.Pages = 0

  /**
   * 是否停止
   */
  this.IsStop = false

  /**
   * 是否续传文件
   */
  this.IsContinue = false

  /**
   * 文件是否上传完成
   */
  this.IsComplete = false

  /**
   * 文件错误
   */
  this.UploadError = null

  /**
   * 上传过程
   */
  this.UploadProcess = null

  /**
   * 数据缓冲
   */
  this.DataBuffer = null

  /**
   * 数据缓冲
   */
  this.DataBytes = []

  /**
   * 文件流
   */
  this.UploadBytes = 0

  /**
   * 是否解压
   */
  this.IsRealName = false

  /**
   *
   */
  this.ContainerId = null

  /**
   * 保存到服务器端的文件名称
   */
  this.FileID = (function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = (Math.random() * 16) | 0,
        v = c == 'x' ? r : (r & 0x3) | 0x8
      return v.toString(16)
    })
  })()

  /**
   * 文件id
   */
  this.ID = Math.floor(Math.random() * 0x10000).toString(16)

  /**
   * 加载文件
   */
  this.LoadCallBack = null

  /**
   * 计算分片总数
   */
  if (Math.floor(this.FileSize % this.PageSize) > 0) {
    this.Pages = Math.floor(this.FileSize / this.PageSize) + 1
  } else {
    this.Pages = Math.floor(this.FileSize / this.PageSize)
  }

  /**
   * 重置
   */
  this.Reset = function () {
    this.PageIndex = 0
    this.UploadBytes = 0
  }

  /**
   * 文件流转Base64
   */
  this.toBase64String = function () {
    var binary = ''
    var bytes = new Uint8Array(this.DataBuffer)
    var len = bytes.byteLength

    for (var i = 0; i < len; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    return window.btoa(binary)
  }

  /**
   * Base64转文件流
   */
  this.toBytes = function (data) {
    var bstr = atob(data),
      n = bstr.length,
      u8Arr = new Uint8Array(n)

    while (n--) {
      u8Arr[n] = bstr.charCodeAt(n)
    }
    this.DataBytes.push(u8Arr)
  }

  /**
   * 上传文件事件
   */
  this.OnLoadData = function (evt) {
    var obj = evt.target['tag']

    if (evt.target.readyState == FileReader.DONE) {
      obj.DataBuffer = evt.target.result

      if (obj.LoadCallBack != null) {
        obj.LoadCallBack(obj)
      }
    } else {
      if (obj.UploadError != null) {
        obj.UploadError(fi, evt.target.error)
      }
    }
  }

  /**
   * 根据每个分片大小，切割文件，读取文件流
   */
  this.Load = function (completed) {
    this.LoadCallBack = completed
    if (this.filereader == null || this.filereader == undefined) this.filereader = new FileReader()
    var reader = this.filereader
    reader['tag'] = this
    reader.onloadend = this.OnLoadData
    var count = this.FileSize - this.PageIndex * this.PageSize
    if (count > this.PageSize) count = this.PageSize
    this.UploadBytes += count
    var blob = this.File.slice(this.PageIndex * this.PageSize, this.PageIndex * this.PageSize + count)

    reader.readAsArrayBuffer(blob)
  }

  /**
   * 上传文件到服务器
   */
  this.OnUploadData = function (file) {
    var channel = file._channel

    if (!file.IsStop) {
      //  发送json到服务器
      channel.send(
        {
          State: 'UPLOAD',
          IsRealName: this.IsRealName,
          UploadGuid: this.UploadGuid,
          FileName: this.FileName,
          parameters: {
            FileID: file.FileID,
            PageIndex: file.PageIndex,
            Pages: file.Pages,
            Base64Data: file.toBase64String(),
            IsContinue: file.IsContinue
          }
        },
        function (result) {
          if (result.status == null || result.status == undefined) {
            file.PageIndex++

            //  更新进度条
            if (file.UploadProcess != null) file.UploadProcess(file)
            if (file.PageIndex < file.Pages) {
              file.Load(file.OnUploadData)
            } else {
              file.IsComplete = true
            }
          } else {
            if (file.UploadError != null) file.UploadError(file, data.status)
          }
        }
      )
    }
  }

  /**
   * 上传文件到服务器
   */
  this.OnDownloadData = function (onDownloadComplete) {
    var channel = this._channel
    var that = this
    that.onDownloadComplete = onDownloadComplete

    if (!this.IsStop) {
      //  发送json到服务器
      channel.send(
        {
          Path: this.RealPath,
          parameters: {
            FileID: this.FileID,
            PageIndex: this.PageIndex,
            Pages: this.Pages,
            IsContinue: this.IsContinue
          }
        },
        function (result) {
          if (result.status == null || result.status == undefined) {
            that.toBytes(result.parameters.Base64Data)
            that.FileSize = result.parameters.Size
            that.Pages = result.parameters.Pages

            //  更新进度条
            if (that.UploadProcess != null) that.UploadProcess(that)
            if (that.PageIndex < result.parameters.Pages) {
              that.PageIndex++
              that.OnDownloadData()
            } else {
              that.IsComplete = true
              console.log('Complete')
              that.Blob = new Blob(that.DataBytes, { type: 'application/octet-stream' })
              that.OnDownloadCompleted(that)
            }
          } else {
            if (that.UploadError != null) that.UploadError(that, data.status)
          }
        }
      )
    }
  }

  /**
   * 加载文件
   */
  this.Upload = function (channel) {
    var fi = this
    fi._channel = channel
    fi.Load(fi.OnUploadData)
  }

  /**
   * 加载文件
   */
  this.ContinueUpload = function (channel) {
    var that = this
    channel.send({ parameters: { FileID: that.FileID, IsContinue: that.IsContinue } })
  }

  /**
   * 解压文件
   */
  this.ExtractFile = function (channel) {
    var that = this
    channel.send({
      State: 'EXTRACT',
      Path: this.RealPath,
      FileName: this.FileName,
      parameters: {
        FileID: that.FileID,
        IsContinue: that.IsContinue
      }
    })
  }

  /**
   * 解压文件
   */
  this.extractFileToGuid = function (channel) {
    var that = this
    channel.send({
      State: 'EXTRACTTOGUID',
      Path: this.RealPath,
      FileName: this.FileName,
      parameters: {
        FileID: that.FileID,
        IsContinue: that.IsContinue
      }
    })
  }
}
